Conversation
Greptile SummaryThis PR bumps the SDK to v0.29.0, introducing a new standalone
Confidence Score: 3/5Not safe to merge — the new Realtime class silently drops all events when the server omits subscription metadata, which is a direct regression in the primary realtime event delivery path The P1 finding in src/services/realtime.ts — specifically Important Files Changed
Reviews (6): Last reviewed commit: "chore: update React Native SDK to 0.29.0" | Re-trigger Greptile |
Made-with: Cursor
Made-with: Cursor
| case 'connected': { | ||
| const messageData = <RealtimeResponseConnected>message.data; | ||
|
|
||
| let session = this.config.session; | ||
| if (!session) { | ||
| const cookie = JSONbig.parse(window.localStorage.getItem('cookieFallback') ?? '{}'); | ||
| session = cookie?.[`a_session_${this.config.project}`]; | ||
| } | ||
| if (session && !messageData?.user) { | ||
| this.realtime.socket?.send(JSONbig.stringify(<RealtimeRequest>{ | ||
| type: 'authentication', | ||
| data: { | ||
| session | ||
| } | ||
| })); | ||
| } | ||
|
|
||
| this.realtime.sendSubscribeMessage(); | ||
| break; |
There was a problem hiding this comment.
Subscribe message sent before authentication confirmation
sendSubscribeMessage() is called immediately after the authentication message is dispatched, with no acknowledgement that the server has authenticated the client. If the server processes subscribe requests before completing the authentication handshake, subscriptions to user-scoped channels will be evaluated without the user's permission context and may silently fall back to guest-level access.
| import type { UploadProgress, Payload } from '../client'; | ||
| import * as FileSystem from 'expo-file-system'; | ||
| import { Platform } from 'react-native'; | ||
| import { Platform as RNPlatform } from 'react-native'; |
There was a problem hiding this comment.
aliased cause name conflict was coming as we are importing realtime.ts from web
| const timestamp = data.timestamp as string; | ||
| const subscriptions = data.subscriptions as string[] | undefined; | ||
|
|
||
| if (!channels || !events || !payload || !subscriptions || subscriptions.length === 0) { |
There was a problem hiding this comment.
Silent event drop when
subscriptions field is absent
handleResponseEvent returns early if subscriptions is undefined or empty, so any event the server sends without subscription-ID metadata is silently discarded — no callback ever fires. The previous implementation in client.ts fell back to channel-name matching in that case (data.channels.some(channel => subscription.channels.includes(channel))). Removing the fallback is a regression: servers that don't yet populate subscriptions in event payloads (or public-channel events sent before a subscribe response arrives) will produce zero callbacks.
Consider keeping the channel-based fallback path when subscriptions is absent or empty:
if (!channels || !events || !payload) {
return;
}
if (subscriptions && subscriptions.length > 0) {
for (const subscriptionId of subscriptions) {
const subscription = this.activeSubscriptions.get(subscriptionId);
if (!subscription) continue;
subscription.callback({ events, channels, timestamp, payload, subscriptions });
}
} else {
// fallback: match by channel name
for (const subscription of this.activeSubscriptions.values()) {
if (channels.some(ch => subscription.channels.has(ch))) {
subscription.callback({ events, channels, timestamp, payload, subscriptions: [] });
}
}
}
This PR contains updates to the SDK for version 0.29.0.
What's Changed